﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Assignment3
{
    class KnowledgeBase
    {
        private List<string> facts;

        public List<string> Facts
        {
            get { return facts; }
            //set { facts = value; }
        }
        private List<string> rules;

        public List<string> Rules
        {
            get { return rules; }
            //set { rules = value; }
        }

        private List<string> properties;

        public List<string> Properties
        {
            get { return properties; }
            //set { variables = value; }
        }

        private List<string> individuals;

        public List<string> Individuals
        {
            get { return individuals; }
            set { individuals = value; }
        }

        public KnowledgeBase(List<string> input)
        {
            facts = new List<string>();
            rules = new List<string>();
            properties = new List<string>();
            individuals = new List<string>();
            PreProcess(input);
        }

        /// <summary>
        /// Process list of string input to separate rules, facts, individuals, and properties
        /// </summary>
        /// <param name="input">List of strings which either a rule or a fact</param>
        public void PreProcess(List<string> input)
        {
            foreach (string line in input)
            {
                string tmpLine = line.Replace(" ", "");
                if (line.Contains(">"))
                {
                    rules.Add(tmpLine);
                }
                else
                {
                    facts.Add(tmpLine);
                    int indexOfBracket = tmpLine.IndexOf('(');
                    if (indexOfBracket != -1)
                    {
                        char[] delimiter = { '(' };
                        string[] sublist = tmpLine.Split(delimiter, StringSplitOptions.RemoveEmptyEntries);
                        string property = sublist[0];
                        if (!properties.Contains(property))
                            properties.Add(property);

                        char[] trimValue = { ')' };
                        string individual = sublist[1].Trim(trimValue);
                        if (!individuals.Contains(individual))
                            individuals.Add(individual);
                    }
                }
            }
        }

        public void AddNewFacts(List<string> newfacts)
        {
            foreach (string fact in newfacts)
            {
                facts.Add(fact);
                int indexOfBracket = fact.IndexOf('(');
                if (indexOfBracket != -1)
                {
                    char[] delimiter = { '(' };
                    string[] sublist = fact.Split(delimiter, StringSplitOptions.RemoveEmptyEntries);
                    string property = sublist[0];
                    if (!properties.Contains(property))
                        properties.Add(property);

                    char[] trimValue = { ')' };
                    string individual = sublist[1].Trim(trimValue);
                    if (!individuals.Contains(individual))
                        individuals.Add(individual);
                }
            }
        }

        public List<string> ReasoningNewFacts(ref List<string> newFacts)
        {
            newFacts.Clear();
            foreach (string rule in rules)
            {
                char[] delimter = { '>' };
                string[] conditionSplit = rule.Split(delimter, StringSplitOptions.RemoveEmptyEntries);

                string antecedents = conditionSplit[0];

                char[] spaceDelimter = { ',' };
                string[] listOfAntecdent = antecedents.Split(spaceDelimter, StringSplitOptions.RemoveEmptyEntries);

                string derived = conditionSplit[1];

                bool conditionMet = true;
                int indexOfBracket = derived.IndexOf('(');
                if (indexOfBracket == -1 || derived.IndexOf(')') - indexOfBracket != 2)
                {
                    foreach (string antecedent in listOfAntecdent)
                    {
                        if (!facts.Contains(antecedent))
                            conditionMet = false;
                    }
                    if (conditionMet && !facts.Contains(derived))
                        newFacts.Add(derived);
                }
                else
                {
                    foreach (string individual in individuals)
                    {
                        conditionMet = true;

                        foreach (string antecedent in listOfAntecdent)
                        {
                            string tmp = antecedent.Substring(0, antecedent.IndexOf('(') + 1);
                            tmp += individual + ")";
                            if (!facts.Contains(tmp))
                                conditionMet = false;
                        }

                        derived = derived.Substring(0, derived.IndexOf('(') + 1) + individual + ")";

                        if (conditionMet && !facts.Contains(derived))
                        {
                            newFacts.Add(derived);
                        }
                    }

                }
            }
            return newFacts;
        }
    }
}
